﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Configurations;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;

namespace Pixysoft.Framework.Logs.Core
{
    class LogCommand : ILogCommand
    {
        bool crossFiles = false;
        string module = null;
        string filepath;
        string fileFullName;//不是包含路径，而是包含了后缀
        LogLevel level = LogLevel.ALL;
        LogCommandRangeConstraint range = new LogCommandRangeConstraint();

        public LogCommand(string filepath, string fileFullName)
        {
            this.filepath = filepath;

            this.fileFullName = fileFullName;
        }


        public ILogDocument ExecuteReader()
        {
            LogDocument doc = new LogDocument(XmlManager.CreateNode(StringHelper.default_element_document));

            foreach (string file in GetSearchFiles())
            {
                IXmlTree tree = GetXmlTree(file);

                foreach (IXmlNode node in tree.Node)
                {
                    ILogRecord record = doc.Records.Add(node);
                }
            }

            doc.Records.Sort();

            return doc;
        }

        public string SerializeReader()
        {
            StringBuilder builder = new StringBuilder();

            foreach (string file in GetSearchFiles())
            {
                IXmlTree tree = GetXmlTree(file);

                foreach (string str in tree.Serialize())
                    builder.AppendLine(str);
            }

            return builder.ToString();
        }

        public LogLevel Level
        {
            get
            {
                return level;
            }
            set
            {
                level = value;
            }
        }

        public ILogCommandRangeConstraint Range
        {
            get { return range; }
        }

        public bool CrossFiles
        {
            get
            {
                return crossFiles;
            }
            set
            {
                crossFiles = value;
            }
        }

        public string Module
        {
            get
            {
                return this.module;
            }
            set
            {
                this.module = value;
            }
        }


        private List<string> GetSearchFiles()
        {
            List<string> list = new List<string>();

            if (File.Exists(filepath + fileFullName))
                list.Add(filepath + fileFullName);

            if (!crossFiles)
            {
                return list;
            }

            foreach (string file in GetCrossFiles())
            {
                list.Add(file);
            }

            return list;
        }

        /// <summary>
        /// 取得区间内的搜索文本
        /// </summary>
        /// <returns></returns>
        private List<string> GetCrossFiles()
        {
            List<string> list = new List<string>();

            //10-02-06 返回空 不抛异常

            if (!Directory.Exists(filepath))
                return list;

            int index = fileFullName.LastIndexOf('.');

            if (index < 0)
                return list;

            string searchfilename = fileFullName.Substring(0, index);

            bool outbounded = false;

            foreach (string desFileWithPathName in Directory.GetFiles(filepath))
            {
                string desFileFullName = StringFilter.GetFileName(desFileWithPathName);

                if (string.IsNullOrEmpty(desFileFullName))
                    continue;

                if (!desFileFullName.EndsWith(StringHelper.default_log_postfix, StringComparison.OrdinalIgnoreCase))
                    continue;

                if (!desFileFullName.StartsWith(searchfilename, StringComparison.OrdinalIgnoreCase))
                    continue;

                if (desFileFullName.Equals(fileFullName, StringComparison.OrdinalIgnoreCase))
                    continue;


                DateTime lasttime = DateTime.MinValue;

                if (!StringHelper.TryParseFileSequence(desFileFullName, out lasttime))
                    continue;

                if (lasttime < range.From)
                    continue;

                if (lasttime < range.To)
                {
                    list.Add(desFileWithPathName);

                    continue;
                }

                //10-02-26 bug!可能出现等于

                if (lasttime >= range.To && !outbounded)
                {
                    outbounded = true;

                    list.Add(desFileWithPathName);

                    continue;
                }

                if (lasttime >= range.To && outbounded)
                {
                    break;
                }
            }

            list.Sort();

            return list;
        }

        /// <summary>
        /// 取得搜索结果
        /// </summary>
        /// <returns></returns>
        private IXmlTree GetXmlTree(string file)
        {
            IXmlCommand command = XmlManager.CreateCommand(file);

            command.Element = StringHelper.default_element_log;

            if (level != LogLevel.ALL && level != LogLevel.OFF)
                command.Constraints.And(StringHelper.default_attribute_level).Equal(StringHelper.GetLogLevelString(level));

            if (range.From != DateTime.MinValue)
                command.Constraints.And<DateTime>(StringHelper.default_attribute_time).GreatEqual(range.From, StringHelper.default_log_dateformat);

            if (range.To != DateTime.MaxValue)
                command.Constraints.And<DateTime>(StringHelper.default_attribute_time).LessEqual(range.To, StringHelper.default_log_dateformat);

            if (!string.IsNullOrEmpty(module))
                command.Constraints.And<string>(StringHelper.default_attribute_module).Equal(module.Trim());

            IXmlTree tree = command.ExecuteReader();

            return tree;
        }
    }
}
